#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> /* 使用sockaddr_in */
#include <strings.h>
#include <arpa/inet.h>
#include <functional>
#include <string>

#include "Log.hpp"
#include "InterAddr.hpp"
using namespace LogModule;

const int defaultSocketFd = -1;

using Ufunc_t = std::function<void(int sockfd, const std::string &, InterAddr&)>;

/* 服务端只负责接收消息即可 */
class UDPSever
{
public:
    UDPSever(const uint16_t port, Ufunc_t func)
        : _socket_fd(defaultSocketFd),
          _port(port),
          _func(func),
          _isrunning(false)
    {
    }

    /*
    初始化:
    1. 创建socket套接字
    2. bind指定的服务器IP + Port
    */
    void Init()
    {
        /* 1. 创建socket套接字 */
        _socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
        /*
        （1） AF_INET 表示IPv4协议
        （2） SOCK_DGRAM 数据报，表示使用UDP网络协议
        （3） 0 表示系统默认匹配TCP/UDP
        */
        if (_socket_fd < 0)
        {
            LOG(LogLevel::FATAL) << "create socket fail!";
            exit(-1);
        }
        LOG(LogLevel::INFO) << "create socket success! " << _socket_fd;
        /* 2. bind指定的服务器IP + Port */
        /* 2.1 填充local */
        InterAddr local(_port);

        /* 2.2 bind指定服务器IP + Port */
        int n = bind(_socket_fd, (const sockaddr*)&local.GetAddr(), sizeof(local.GetAddr()));
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind sever fail!";
            exit(-2);
        }
        LOG(LogLevel::INFO) << "bind sever success! " << _socket_fd;
    }

    /*
    启动:
    1. 监听服务器消息
    2. 调用执行回调函数
    */
    void Start()
    {
        _isrunning = true;
        while(_isrunning)
        {
            /* 1. 监听服务器消息 */
            char buffer[1024];
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t s = recvfrom(_socket_fd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&peer, &len);
            if(s < 0)
            {
                LOG(LogLevel::FATAL) << "recvfrom fail!";
                exit(-3);
            }
            LOG(LogLevel::INFO) << "recvfrom success!";
            buffer[s] = 0;
            InterAddr Clientaddr(peer);

            /* 2. 调用回调函数 */
           _func(_socket_fd, buffer, Clientaddr);
        }
        _isrunning = false;
    }

    ~UDPSever() {}

private:
    int _socket_fd; /* 套接字 */
    uint16_t _port; /* 端口号 */
    Ufunc_t _func;   /* 回调函数*/
    bool _isrunning;/* 表示服务端是否运行 */
};